﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace CommonUtils.CodeFactory
{
    public static class FunctionUtil
    {
        //判断代码是不是方法
        public static bool Judge(string line, out string key, out bool isStruct)
        {
            key = null;
            isStruct = false;

            line = line.Trim();
            if (line.StartsWith("//"))
                return false;

            line = line.SubstringStartByFirst('\'');
            line = line.SubstringStartByFirst('"');
            if (!line.Contains('('))
                return false;

            line = line.SubstringStartByFirst('(');
            var cells = line.Split(' ', StringSplitOptions.RemoveEmptyEntries);
            if (cells.Contains("="))
                return false;
            if (cells.Length < 2)
                return false;

            isStruct = (cells.Length == 2) && (cells[0].Equals("private", "public", "static"));

            key = cells[cells.Length - 1];
            return true;
        }


        public static void Simplify(string path)
        {
            var code = FileUtil.GetText(path);
            var comments = code.GetBetween("/*", "*/", true);
            code = code.Remove(comments);
            var lines = code.GetLines();
            var newCode = new List<string>();

            var hasFunction = false;
            var function = new Function("", "", false);

            foreach (var line in lines)
            {
                if (!hasFunction && Judge(line, out string key, out bool isStruct))
                {
                    function = new Function(line, key, isStruct);
                    hasFunction = true;
                }

                if (hasFunction)
                {
                    if (function.CountKeyAndJudgeFinish(line))
                    {
                        newCode.Add(function.GetCode(FunctionOperation.Simplify));
                        hasFunction = false;
                        function.Key.Print();
                        function.GetCode().Print();
                        function.GetCode(FunctionOperation.Simplify).Print();
                    }
                    continue;
                }

                newCode.Add(line);
            }

            if (hasFunction)
            {
                ConsoleUtil.Write("Bug Function !");
                function.GetCode().Print();
            }

            foreach (var item in comments)
                newCode.Insert(0, item);

            FileUtil.Save(path, newCode.GetText());
        }

        public static void Order(string path)
        {
            var code = FileUtil.GetText(path);
            var comments = code.GetBetween("/*", "*/", true);
            code = code.Remove(comments);
            var lines = code.GetLines();
            var newCode = new List<string>();

            var hasFunction = false;
            var function = new Function("", "", false);
            var functions = new List<Function>();
            var functionIndex = 0;

            foreach (var line in lines)
            {
                if (!hasFunction && Judge(line, out string key, out bool isStruct))
                {
                    function = new Function(line, key, isStruct);
                    functionIndex = function.AddComment(newCode);
                    hasFunction = true;
                }

                if (hasFunction)
                {
                    if (function.CountKeyAndJudgeFinish(line))
                    {
                        functions.Add(function);
                        hasFunction = false;
                        function.Key.Print();
                        function.GetCode().Print();
                    }
                    continue;
                }

                newCode.Add(line);
            }

            if (hasFunction)
            {
                ConsoleUtil.Write("Bug Function !");
                function.GetCode().Print();
            }

            functions = functions.OrderByDescending(m => m.Define).OrderByDescending(m => m.Key).OrderBy(m => m.IsStruct).ToList();
            var firstLine = newCode[functionIndex - 1].Trim() == "{";
            for (int index = 0; index < functions.Count; index++)
            {
                var item = functions[index];
                newCode.Insert(functionIndex, item.GetCode());
                if (!firstLine || index != functions.Count - 1)
                    newCode.Insert(functionIndex, null);
            }

            foreach (var item in comments)
                newCode.Insert(0, item);

            FileUtil.Save(path, newCode.GetText());
        }

        public static void AlignLambdas(string path)
        {
            var code = FileUtil.GetText(path);
            var comments = code.GetBetween("/*", "*/", true);
            code = code.Remove(comments);
            var lines = code.GetLines();
            var newCode = new List<string>();

            var hasFunction = false;
            var function = new Function("", "", false);

            foreach (var line in lines)
            {
                if (!hasFunction && Judge(line, out string key, out bool isStruct))
                {
                    function = new Function(line, key, isStruct);
                    hasFunction = true;
                }

                if (hasFunction)
                {
                    if (function.CountKeyAndJudgeFinish(line))
                    {
                        newCode.Add(function.GetCode(FunctionOperation.LambdaFormat));
                        hasFunction = false;
                        function.Key.Print();
                        function.GetCode().Print();
                        function.GetCode(FunctionOperation.LambdaFormat).Print();
                    }
                    continue;
                }

                newCode.Add(line);
            }

            if (hasFunction)
            {
                ConsoleUtil.Write("Bug Function !");
                function.GetCode().Print();
            }

            foreach (var item in comments)
                newCode.Insert(0, item);

            FileUtil.Save(path, newCode.GetText());
        }
    }
}
